# -*- coding: utf-8 -*-
import datetime
import os
import time
import zipfile
from collections.abc import Iterable
from tempfile import NamedTemporaryFile
from typing import Any
from typing import List
from urllib.parse import quote

from fastapi.responses import Response
from openpyxl import Workbook
from orjson import dumps
from pydantic import BaseModel, parse_obj_as
from sqlalchemy import Row
from config.config import CFG
from log import log
from .myJsonHandler import orjson_dumps
import re

class RespResult(BaseModel):
    success: bool
    message: str
    code: int
    result: object | List[object] | None


def get_current_timestamp():
    return datetime.datetime.now().timestamp()


def get_current_time():
    now = datetime.datetime.now()
    # 格式化当前日期为 YYYY-MM-DD 格式
    formatted_date = now.strftime("%Y-%m-%d %H:%M:%S")
    return formatted_date


def is_iterable(obj):
    return isinstance(obj, Iterable) and not isinstance(obj, str)


# def is_iterable2(obj):
#     try:
#         iter(obj)
#         return True
#     except TypeError:
#         return False

def toPydantic(source, schema):
    # print(source)
    # print(inspect.isclass(source))
    # print(isinstance(source, Db_Base))
    if isinstance(source, list):
        return [toPydantic(s, schema) for s in source]
    else:
        if schema:
            return schema.from_orm(source)
        else:
            return parse_obj_as(schema, source)
            # return parse_obj_as(List[schema], source)
            # model_obj = model(** source.__dict__)
            # if inspect.isclass(source) and isinstance(source, SqlBase):


def result(message: str | None = "操作成功", success: bool = True, status: int = 200, data: Any = None,
           schema: Any = None):
    if schema and issubclass(schema, BaseModel):
        print('is valid schema')
        data_obj = toPydantic(data, schema)
    else:
        print('is invalid schema')
        data_obj = data

    res = RespResult(
        success=success,
        message=message,
        code=status,
        result=data_obj
    )
    return res


def remove_empty_values(data, exclude_null, and_exclude_empty_obj, include, exclude):
    if isinstance(data, dict):
        return {k: remove_empty_values(v, exclude_null, and_exclude_empty_obj, include, exclude) for k, v in data.items()
                if (not exclude_null or v or v == 0 or v == False or (not and_exclude_empty_obj and (v == [] or v == {})))
                and (not include or (include and k in include))
                and (not exclude or (exclude and k not in exclude))
                }
    elif isinstance(data, list):
        return [remove_empty_values(item, exclude_null, and_exclude_empty_obj, include, exclude) for item in data if item or item == 0 or item == False]
    else:
        return data


def has_func(obj, func):
    return hasattr(obj, func) and callable(getattr(obj, func))


# 递归解析对象集群
def parse_obj(obj):
    if not obj:
        return obj
    elif isinstance(obj, Row):
        return dict(obj._asdict())
    elif isinstance(obj, list):
        return [parse_obj(item) for item in obj]
    elif has_func(obj, 'to_dict'):
        return obj.to_dict()
    elif isinstance(obj, datetime.datetime):
        return obj.strftime("%Y-%m-%d %H:%M:%S")
    else:
        return obj


def json_result(message: str | None = "操作成功", success: bool = True, status: int = 200,
                data: Any = None, exclude_null=True, and_exclude_empty_obj=False, include: set = None, exclude: set = None, use_serializer=False) -> bytes:
    # log.info("original data: {0}", data)
    if exclude is None:
        exclude = {}
    if use_serializer:
        log.info("orjson_dumps use_serializer....")
        content = orjson_dumps(dict(
            success=success,
            message=message,
            code=status,
            result=data
        ))
    else:
        res = parse_obj(data)
        log.info("res:{0}", type(res))
        # 去空值处理
        if res:
            res = remove_empty_values(res, exclude_null, and_exclude_empty_obj, include, exclude)

        content = dumps(dict(
            success=success,
            message=message,
            code=status,
            result=res
        ))

    return content


def json_reps(content: bytes):
    return Response(
        content=content,
        media_type="application/json; charset=UTF-8",
    )


def json_result_reps(message: str | None = "操作成功", success: bool = True, status: int = 200,
                     data: Any = None, exclude_null=True, exclude_empty_obj=False, include: set = None, exclude: set = None, use_serializer=False):
    return json_reps(
        json_result(
            message,
            success,
            status,
            data,
            exclude_null,
            exclude_empty_obj,
            include,
            exclude,
            use_serializer
        ))


def download_zip(content: bytes, filename: str):
    response = Response(content=content, media_type="application/zip")
    encoded_filename = quote(filename.encode('utf-8'))
    content_disposition = f"attachment; filename*=UTF-8''{encoded_filename}"
    response.headers["Content-Disposition"] = content_disposition
    return response


def download_file_stream(content: bytes, filename: str):
    header = {}
    encoded_filename = quote(filename.encode('utf-8'))
    content_disposition = f"attachment; filename*=UTF-8''{encoded_filename}"
    header.update({'Content-Type': 'application/octet-stream'})
    header.update({f'Content-Disposition': content_disposition})
    return Response(
        content=content,
        headers=header
    )


async def zip_files(files: list, file_suffix='.xlsx') -> bytes:
    dest_file = None
    isDelete = True
    if os.name == 'nt':
        # dest_file = "e:\\tmp\\" + str(int(time.time())) +file_suffix
        isDelete = False
    with NamedTemporaryFile(delete=isDelete) as temp_zip_file:
        with zipfile.ZipFile(temp_zip_file, 'w') as zip_file:
            # 创建多个Excel文件
            for f in files:
                obj, filename = f.values()
                # print(wb, filename)
                with NamedTemporaryFile(suffix=file_suffix) as temp_excel_file:
                    dest_file = dest_file or temp_excel_file.name
                    if isinstance(obj, Workbook):
                        obj.save(dest_file)
                    # 重新打开临时文件以读取内容，并添加到ZIP文件中
                    with open(dest_file, 'rb') as excel_file:
                        # zip_file.write(excel_file, f.filename)
                        data = excel_file.read()
                        zip_file.writestr(filename, data)
        # 将ZIP文件的内容读取到内存中
        temp_zip_file.seek(0)
        zip_content = temp_zip_file.read()
        #temp_zip_file.close()
        return zip_content


def is_number(string):
    pattern = re.compile(r'^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$')
    return bool(pattern.match(string))